Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SPORES in v0.7.0 as a generalisable mode #716

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

FLomb
Copy link
Contributor

@FLomb FLomb commented Nov 20, 2024

Fixes #431

Summary of changes in this pull request

  • Introduces a spores scenario as part of the national-scale example model
  • Introduces a custom math file in the national-scale example model, which is activated in the spores scenario to create a slack cost constraint
  • It provides a dedicated notebook to generate SPORES iteratively based on the spores scenario overrides and a custom Python function for assigning penalties at each iteration.

Based on internal discussions, we have come to realise that there are many ongoing SPORES developments that may be hard to always reconduct to a monolithic run mode in the core code. Instead, it may be best to implement SPORES as a method that simply allows you to run a model in plan mode once, and then N number more times with some external function being applied between each run, with the user providing that function. This way, this mode could be used not only for SPORES but also for robustness analysis and other things.

This PR aims to show how SPORES can be indeed already used in v0.7.0 based on default software functionality plus a simple for-loop and a custom Python function to assign penalties for decision variables at each iteration of the loop. To move from this to the generalised mode described above, we would only need to decide how to make some bits of this code (such as the number of iterations, and the custom Python function) a default request for inputs to the user.

The new run-iteratively-with-a-function mode (a better name must be found, could also be spores-and-more if the main application remains SPORES), would essentially require the following three key inputs: 1) how many iterations to run; 2) what function to apply at each iteration; and 3) what backend parameter to updated based on the function.

Reviewer checklist

  • Test(s) added to cover contribution
  • Documentation updated
  • Changelog updated
  • Coverage maintained or improved

@FLomb FLomb added enhancement v0.7 (upcoming) version 0.7 labels Nov 20, 2024
@FLomb FLomb changed the base branch from main to add-broadcast-param-data November 20, 2024 15:21
@FLomb FLomb marked this pull request as draft November 20, 2024 15:23
@FLomb FLomb requested a review from brynpickering November 20, 2024 15:24
Updated to remove outdated link to local path
Updated to remove outdated reference to Gurobi, which I was using locally
@FLomb
Copy link
Contributor Author

FLomb commented Nov 20, 2024

I see that building the docs fails because I am using matplotlib, which isn't part of the default Calliope environment. I will remove the plotting part, for now. We can later re-implement it via a supported library, or just leave it out.

Updated to remove plotting with matplotlib, which is not supported by the default Calliope environment. Plotting can be re-implemented later, if desirable
# ### Definition of the penalty-assignment methods

# %%
def scoring_integer(results, backend):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no doubt that this function can be majorly shortened by someone with deeper experience of these data structures

Base automatically changed from add-broadcast-param-data to main November 20, 2024 16:26
@brynpickering brynpickering marked this pull request as ready for review December 24, 2024 18:12
@brynpickering
Copy link
Member

@FLomb I've updated the approach to minimise the input requirements from the user. The main change is that there is now no longer a spores-specific cost class. Instead, the objective is changed in the math. Updating this objective with user-defined math would allow a user to update how the spores scores are translated to penalties in the optimisation problem.

The SPORES mode stuff is currently untested although you can see that it works in the example notebook.

I hope that some of the hardcoding of params in model.py can go away with the implementation of #712.

The SPORES mode stuff will also move out of model.py (initial work on that is also in #712). Hopefully, though, you can see that it is on the verge of being generalisable - there is an "iterative optimisation" controller that calls a model updater. My idea would be to scrub "spores" from this controller and just have it so that it can run with a supplied updater function, the SPORES mode one being one of them. This would allow for other iterative updaters (including custom SPORES algorithms) to be supplied by the user and managed by the controller.

Copy link

codecov bot commented Dec 24, 2024

Codecov Report

Attention: Patch coverage is 95.49550% with 5 lines in your changes missing coverage. Please review.

Project coverage is 96.54%. Comparing base (485b3d5) to head (9818b70).

Files with missing lines Patch % Lines
src/calliope/backend/latex_backend_model.py 77.77% 1 Missing and 1 partial ⚠️
src/calliope/cli.py 33.33% 1 Missing and 1 partial ⚠️
src/calliope/backend/gurobi_backend_model.py 92.30% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #716      +/-   ##
==========================================
+ Coverage   96.40%   96.54%   +0.13%     
==========================================
  Files          35       35              
  Lines        4397     4457      +60     
  Branches      599      605       +6     
==========================================
+ Hits         4239     4303      +64     
+ Misses         68       65       -3     
+ Partials       90       89       -1     
Files with missing lines Coverage Δ
src/calliope/backend/backend_model.py 98.01% <100.00%> (+0.02%) ⬆️
src/calliope/backend/pyomo_backend_model.py 98.15% <100.00%> (+0.03%) ⬆️
src/calliope/backend/where_parser.py 98.20% <100.00%> (ø)
src/calliope/model.py 97.95% <100.00%> (+0.42%) ⬆️
src/calliope/postprocess/postprocess.py 100.00% <100.00%> (+1.81%) ⬆️
src/calliope/schemas/config_schema.py 100.00% <100.00%> (+5.31%) ⬆️
src/calliope/backend/gurobi_backend_model.py 95.41% <92.30%> (+0.12%) ⬆️
src/calliope/backend/latex_backend_model.py 95.65% <77.77%> (-1.25%) ⬇️
src/calliope/cli.py 82.05% <33.33%> (+0.09%) ⬆️

@brynpickering
Copy link
Member

@irm-codebase & @FLomb if you could check this PR that would be great!

Copy link
Contributor

@irm-codebase irm-codebase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, although a bit hard to follow in places. Added a few suggestions.

irm-codebase
irm-codebase previously approved these changes Feb 21, 2025
Copy link
Contributor

@irm-codebase irm-codebase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good.

I am tentatively approving, with some suggestions on naming.

@brynpickering
Copy link
Member

@irm-codebase I've updated the implementation slightly to get the SPORES maths showing in the docs (you can see it under "pre-defined math" in the PR build). It requires an update to our math docs to show all defined objectives by default. To differentiate between those objectives I'm now adding a suffix to the objective name to say whether or not it is activated. Question is, is this confusing for e.g. the plan mode math (that it has (active) after the objective name)?

irm-codebase
irm-codebase previously approved these changes Feb 25, 2025
Copy link
Contributor

@irm-codebase irm-codebase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brynpickering changes look fine, but I am not sure why the code difference is showing changes from main...

Approved, but let's be careful just in case to avoid overwriting things on main

@brynpickering
Copy link
Member

but I am not sure why the code difference is showing changes from main.

Which changes is it showing?

@irm-codebase
Copy link
Contributor

@brynpickering ignore, I was incorrect (just goes to show that you should do reviews while well-rested).
For some reason I confused the sense in the math with the pydantic PR, but that is not the case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement v0.7 (upcoming) version 0.7
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reincorporate spores mode in v0.7.0
3 participants